/*
 * Copyright (C) 2011 Sherlock Downloader
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.sherlock.plugins.loaders;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Properties;

import org.sherlock.commons.plugins.IManager;
import org.sherlock.commons.plugins.model.Plugin;
import org.sherlock.plugins.exceptions.PluginException;

/**
 *
 * @author Sherlock Downloader
 */
public class PluginLoader {

    private Plugin plugin;
    private Properties properties;
    private URLClassLoader loader;
    private String nameFileName;
    private IManager manager;

    public PluginLoader(IManager manager) {
        this.manager = manager;
    }

    public void loadJAR(URL url) throws PluginException {
        try {
            loader = new URLClassLoader(new URL[]{url});
            nameFileName = url.getFile().substring(url.getFile().lastIndexOf("/") + 1);
            loadProperties();
        } catch (IOException ex) {
            throw new PluginException("There was a problem trying to read the properties file. Missing?");
        }
    }

    public ArrayList<String> getDependences() {
        ArrayList<String> dependences = new ArrayList<String>();

        String propertyDependence = properties.getProperty("dependences");
        if (propertyDependence != null) {
            dependences.addAll(Arrays.asList(propertyDependence.split(";")));
        }

        return dependences;
    }

    public Plugin loadPlugin() throws PluginException {
        switch (getPluginType()) {
            case REVEALER:
                plugin = new RevealerLoader().load(loader, properties);
                break;
            case ENGINE:
                plugin = new EngineLoader().load(loader, properties);
                break;
            case VIEW:
                plugin = new ViewLoader().load(loader, manager);
                break;
        }
        if (plugin == null) {
            throw new PluginException();
        }
        plugin.setFileName(nameFileName);
        readMetadata();
        return plugin;
    }

    public Plugin load(URL url) throws PluginException {
        loader = new URLClassLoader(new URL[]{url});        
        try {
            loadProperties();
        } catch (IOException ex) {
            throw new PluginException("There was a problem trying to read "
                    + "the properties file. Missing?");
        }

        switch (getPluginType()) {
            case REVEALER:
                plugin = new RevealerLoader().load(loader, properties);
                break;
            case ENGINE:
                plugin = new EngineLoader().load(loader, properties);
                break;
            case VIEW:
                plugin = new ViewLoader().load(loader, manager);
                break;
        }
        if (plugin == null) {
            throw new PluginException();
        }
        plugin.setFileName(url.getFile().substring(url.getFile().lastIndexOf("/")));
        readMetadata();


        return plugin;
    }

    private Plugin.Type getPluginType() throws PluginException {
        Plugin.Type pluginType = null;

        String type = properties.getProperty("type");
        if (type == null) {
            throw new PluginException("Invalid properties file. Missing type");
        } else {
            try {
                pluginType = Plugin.Type.valueOf(type.toUpperCase());
            } catch (IllegalArgumentException ex) {
                throw new PluginException("Invalid type '" + type + "'");
            }
        }
        return pluginType;
    }

    private Properties loadProperties() throws IOException {
        InputStream stream = null;
        try {            
            stream = loader.getResourceAsStream("plugin.properties");
            if (stream == null) {
                System.out.println("it is null");
                throw new IOException();
            }
            properties = new Properties();
            properties.load(stream);
        } finally {
            if (stream != null) {
                stream.close();
            }
        }

        return properties;
    }

    private void readMetadata() throws PluginException {
        String author = properties.getProperty("author");
        String name = properties.getProperty("name");
        String version = properties.getProperty("version");

        if ((author == null) || (name == null) || (version == null)) {
            throw new PluginException("Invalid properties file");
        }

        plugin.setAuthor(author);
        plugin.setName(name);
        plugin.setVersion(version);
        plugin.setDescription(properties.getProperty("description"));
    }
}

